package parser;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;

public class Parser {
	private HashMap<Character, HashSet<String>> productions=null;
	private HashMap<String,String> tabla;
	private HashSet<Character> noTerminales;
	private HashSet<Character> terminales;
	public static final Character MARCA_EOF= '\\';
	
	public Parser(String str) throws IOException {
		BufferedReader arch=new BufferedReader(new FileReader(str));
		
		productions=new HashMap<Character, HashSet<String>>();
		noTerminales=new HashSet<Character>();
		terminales=new HashSet<Character>();
		
		String aux;
		while((aux=arch.readLine())!=null) {
			String[] prod=aux.split(" ");
			 
			if(prod.length==0 || prod.length>2 || prod[0].length()!=1 || !Character.isUpperCase(prod[0].charAt(0)))
				throw new IOException("Archivo Corrupto");
			if(productions.containsKey(prod[0].charAt(0))) {
				noTerminales.add(prod[0].charAt(0));
				if(prod.length==1){
					productions.get(prod[0].charAt(0)).add("\\");
				} else {
					productions.get(prod[0].charAt(0)).add(prod[1]);
					agregaTerminales(prod[1]);
				}
			} else {
				noTerminales.add(prod[0].charAt(0));
				HashSet<String> set=new HashSet<String>();
				if(prod.length==1){
					set.add("\\");
				}else{
					set.add(prod[1]);
					agregaTerminales(prod[1]);
				}
				productions.put(prod[0].charAt(0), set);
			}
		}
		armaTabla();
	}
	
	private void armaTabla() {
		tabla=new HashMap<String,String>();
		
		for(Character noTer: productions.keySet()){
			for(String prod: productions.get(noTer)) {
				tabla.put(""+noTer+prod.charAt(0),prod);
			}
			ArrayList<Character> prim=getPrimeros(noTer);
			if(prim.contains('\\')) {
				for(char a: terminales) {
					if(!prim.contains(a)) {
						tabla.put(""+noTer+a,"\\");
					}
				}
			}
		}
	}
	
	public String getNextProd(char noTer, char l) {
		return tabla.get(""+noTer+l);
	}
	
	private ArrayList<Character> getPrimeros(char c) {
		ArrayList<Character> resp=null;
		if(productions.containsKey(c)) {
			resp=new ArrayList<Character>();
			for(String str: productions.get(c)){
				resp.add(str.charAt(0));
			}
		}
		return resp;
	}
	
	private void agregaTerminales(String str) {
		for(char a: str.toCharArray()) {
			if(!Character.isUpperCase(a))
				terminales.add(a);
		}
	}
}
